﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestPlanWordWriter.Common.Word
{
    public class ContentControlIdentification
    {
        private const string TEST_PLAN_DOCWRITER_PREFIX_V1 = "TestPlanDocWriter";
        private const string TEST_PLAN_DOCWRITER_PREFIX_V2 = "TPDW";
        private const string TEST_PLAN_TOKEN_SEPARATOR = "#";

        //TestPlanDocWriter#1 -> None in order to support legacy documents
        //TestPlanDocWriter#1#MostRecent
        //TestPlanDocWriter#1#SpecificBuild#build_number
        //TestPlanDocWriter#1#AllResults
        public ContentControlIdentification(string tag)
        {
            this.ResultsSettings = new TestResultsSettings();
            this.ResultsSettings.Options = TestResultsOptions.None;
            this.ResultsSettings.SpecificBuildNumber = null;
            this.ControlType = TestControlType.TestPlanControl;
            if (tag != null && TagPrefixIsTestControl(tag))
            {
                this.IsTestPlanControl = true;
                ParseTag(tag);
            }
            else
            {
                this.IsTestPlanControl = false;
            }
        }

        public bool IsTestPlanControl { get; private set; }
        public int PlanIdFromControlTag { get; private set; }
        public TestResultsSettings ResultsSettings { get; private set; }
        public string SpecificBuildNumber { get; private set; }
        public TestControlType ControlType { get; private set; }

        public static string BuildTag(int testPlanId)
        {
            string tag = string.Format(
                "{0}{1}{2}", 
                TEST_PLAN_DOCWRITER_PREFIX_V2, 
                TEST_PLAN_TOKEN_SEPARATOR, 
                testPlanId.ToString());
            return tag;
        }

        public static string BuildTag(int testPlanId, TestResultsSettings settings)
        {
            if (settings.Options == TestResultsOptions.Build)
            {
                return string.Format(
                    "{0}{1}{2}{3}{4}{5}{6}",
                    TEST_PLAN_DOCWRITER_PREFIX_V2,
                    TEST_PLAN_TOKEN_SEPARATOR,
                    testPlanId.ToString(),
                    TEST_PLAN_TOKEN_SEPARATOR,
                    settings.Options.ToString(),
                    TEST_PLAN_TOKEN_SEPARATOR,
                    settings.SpecificBuildNumber
                    );
            }
            else
            {
                return string.Format(
                    "{0}{1}{2}{3}{4}",
                    TEST_PLAN_DOCWRITER_PREFIX_V2,
                    TEST_PLAN_TOKEN_SEPARATOR,
                    testPlanId.ToString(),
                    TEST_PLAN_TOKEN_SEPARATOR,
                    settings.Options.ToString()
                    );
            }
        }

        private bool TagPrefixIsTestControl(string tag)
        {
            //Support of V1 prefix
            if (tag.StartsWith(TEST_PLAN_DOCWRITER_PREFIX_V1) || tag.StartsWith(TEST_PLAN_DOCWRITER_PREFIX_V2))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void ParseTag(string tag)
        {
            if (tag == null)
                throw new ApplicationException("Null value in tag is not allowed");

            string[] tokens = tag.Split(TEST_PLAN_TOKEN_SEPARATOR.ToCharArray());
            if (tokens.Length == 2 || tokens.Length == 3 || tokens.Length == 4)
            {
                this.PlanIdFromControlTag = Int32.Parse(tokens[1]);
                if (tokens.Length > 2)
                {
                    TestResultsOptions options;
                    //TryParse ResultsOptions
                    if (Enum.TryParse<TestResultsOptions>(tokens[2], out options))
                    {
                        this.ResultsSettings.Options = options;
                        if (options != TestResultsOptions.None)
                        {
                            this.ControlType = TestControlType.TestResultsControl;
                        }

                        if (options == TestResultsOptions.Build)
                        {
                            if (tokens.Length == 4)
                            {
                                if (!string.IsNullOrEmpty(tokens[3]))
                                {
                                    this.ResultsSettings.SpecificBuildNumber = tokens[3];
                                }
                                else
                                {
                                    throw new ApplicationException(string.Format("Bad format in tag, parsing ResultsOptions there is no SpecificBuildNumber. Tag content={0}", tag));
                                }
                            }
                            else
                            {
                                throw new ApplicationException(string.Format("Bad format in tag, parsing ResultsOptions there is no SpecificBuildNumber. Tag content={0}", tag));
                            }
                        }
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Bad format in tag, parsing ResultsOptions. Tag content={0}", tag));
                    }
                }
            }
            else
            {
                throw new ApplicationException(string.Format("Bad format in tag. Tag content={0}", tag));
            }
        }
    }
}
